/**
 * Copyright (c) 2010-2011 julewa.com.  
 * All rights reserved. 
 * 
 * @author Huang Benhua
 * @date 2011-2-20
 * 
**/
package com.julewa.loading;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import com.julewa.freemarker.FreemarkerBuilder;
import com.julewa.freemarker.FreemarkerLoader;


public final class StrutsLoader {
//	public static String PKG_PATH = StrutsLoader.class.getPackage().getName().replace('.', '/');
	private Filter filter = null;
	private String path = "";
	public StrutsLoader(FreemarkerBuilder freemarker){
		path = SystemUtils.getClassesPath() + "_JULEWA_STRUTS_.xml";
		this.initialize();
		this.loadConfig(freemarker);
		freemarker.build(path);
		freemarker.getParameters().clear();
	}
	
	public void load(FilterConfig conf) throws ServletException{
		filter = new org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter();
		filter.init(ContextProxyUtils.getProxy(conf, "struts-default.xml,struts2-plugin.xml,_JULEWA_STRUTS_.xml"));
	};
	public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException,ServletException{
        filter.doFilter(request, response, chain);
    }
	public void close(){
		filter.destroy();
	}
	
	private void initialize(){
		SystemUtils.setProperty("struts.mapper.class",RESTNameMapper.class.getCanonicalName());
		SystemUtils.setDefault("struts.action.extension", "htm");
		SystemUtils.setProperty("struts.convention.default.parent.package", "_JULEWA_PACKAGE_");//, struts.convention.default.parent.package=_JULEWA_PACKAGE_
		SystemUtils.setProperty("struts.freemarker.manager.classname",FreemarkerLoader.class.getCanonicalName());

		SystemUtils.setProperty("struts.convention.action.disableScanning", "false");
		SystemUtils.setProperty("struts.convention.action.name.lowercase","true");
		SystemUtils.setDefault("struts.convention.action.name.separator", "_");
		SystemUtils.setProperty("struts.convention.relative.result.types", "freemarker,dispatcher");// "freemarker,dispatcher");
		//
		String basepkg = 
		SystemUtils.setDefault("struts.convention.default.locators.basePackage", SystemUtils.getProperty("system.package"));
		SystemUtils.setDefault("struts.convention.action.suffix","Action");
		basepkg += "." + 
		SystemUtils.setDefault("struts.convention.default.locators","actions");
		SystemUtils.setProperty("struts.convention.default.locators.disable","false");
		SystemUtils.setDefault("struts.convention.result.path", "/WEB-INF/classes/" + basepkg.replace('.', '/'));
		SystemUtils.setProperty("struts.convention.result.flatResult", "true");
		//
		SystemUtils.setProperty("struts.convention.action.checkImplementsAction", "true"); 
		//SystemUtils.setProperty("struts.mapper.alwaysSelectFullNamespace", "false");
		//SystemUtils.setProperty("struts.convention.redirect.to.slash", "true");
		//
		String v = SystemUtils.getProperty("struts.convention.exclude.packages");
		v =  "com.julewa.*, org.apache.*,org.springframework.*,com.ibatis.*,org.hibernate.*," +  v;
		SystemUtils.setProperty("struts.convention.exclude.packages", v);
		//
		
		//
		SystemUtils.setDefault("struts.i18n.encoding", SystemUtils.getProperty("system.encoding"));
		//
	}
	public class GResult{
		private String name, value, type;
		public GResult(String k, String v){
			int idx = k.indexOf('.');
			if(idx < 0){
				name = k;
				type="freemarker";
			}else{
				name=k.substring(0, idx);
				type=k.substring(idx + 1).toLowerCase();
			}
			//
			v = v.trim();
			value = v;
			//
			if("action".equalsIgnoreCase(type)){
				type = "redirectAction";
			}
			if("chain".equalsIgnoreCase(type) || "redirectaction".equalsIgnoreCase(type)){
				idx = v.lastIndexOf('/');
				if(idx < 0)return;
				StringBuffer def = new StringBuffer();
				def.append("<param name=\"namespace\">");
				def.append((idx == 0)?"/":v.substring(0, idx));
				def.append("</param>");
				def.append("<param name=\"actionName\">");
				def.append(v.substring(idx + 1));
				def.append("</param>");
				value = def.toString();
			}
		}
		public String getName(){return name;};
		public String getValue(){return value;};
		public String getType(){return type;};
	}
	private void loadConfig(FreemarkerBuilder freemarker){
		//
		Map<String, String> constants = new HashMap<String, String>();
		List<GResult> globalResults = new ArrayList<GResult>();
		List<Map<String, Object>> interceptors = new ArrayList<Map<String, Object>>();
		//
		Set<String> keys = SystemUtils.getKeys();
		for(String k:keys){
			if(k.startsWith("struts.REST."))continue;
			if(k.startsWith("struts.")){
				constants.put(k, SystemUtils.getProperty(k));
				continue;
			};
			if(k.startsWith("result.")){
				String v = SystemUtils.getProperty(k);
				if(v.startsWith("#")){
					v = SystemUtils.getProperty("struts.convention.result.path") + "/" + v.substring(1);
				}
				globalResults.add(new GResult(k.substring("result.".length()), v));
			}
		}
		//
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("_name_", "_JULEWA_STRUTS_");
		m.put("_class_", StrutsInterceptor.class.getCanonicalName());
		//
		interceptors.add(m);
		
		//
		String refs[] = SystemUtils.getProperty("interceptors").split(",");
		for(String k:refs){
			if(k == null)continue;
			k = k.trim();
			if(k.equals(""))continue;
			m = new HashMap<String, Object>();
			interceptors.add(m);
			m.put("_name_", k);
			k = "interceptor." + k;
			String v = SystemUtils.getProperty(k);
			k += ".";
			if(!v.equals("")){
				String cs[] = v.split(",");
				m.put("_class_", cs[0]);
				for(int i = 1; i < cs.length; i ++){
					v = cs[i].trim();
					if("".equals(v))continue;
					SystemUtils.setProperty("spring." + k + i, v);
				}
			}
			Map<String, String> mm = new HashMap<String, String>();
			for(String kk:keys){
				if(!kk.startsWith(k))continue;
				mm.put(kk.substring(k.length()), SystemUtils.getProperty(kk));
			}
			if(mm.isEmpty())continue;
			m.put("params", mm.entrySet());
		}
		///
		freemarker.put("constants", constants.entrySet());
		freemarker.put("globalResults", globalResults);
		freemarker.put("interceptors", interceptors);
	}
	
}
